package com.differ.log.core;


import java.lang.reflect.Field;
import java.util.Date;
import java.util.List;

import javax.persistence.Table;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import com.alibaba.fastjson.JSONObject;
import com.differ.log.anno.FieldDesc;
import com.differ.log.anno.ModelDesc;
import com.differ.log.core.dto.LogBean;
import com.differ.log.dao.DifferDao;
import com.differ.log.domain.Log;
import com.differ.log.domain.LogContent;
import com.differ.log.enums.OperateType;

import de.danielbechler.diff.ObjectDiffer;
import de.danielbechler.diff.ObjectDifferBuilder;
import de.danielbechler.diff.node.DiffNode;
import de.danielbechler.diff.node.Visit;

@Component
public class DiffUtils {
	
	@Autowired
	private DifferDao differDao;
	public LogBean exctor(final Object idVlue, final Object base, final Object working, final Class<?> clazz,
			OperateType operateType) {
		ObjectDiffer objectDiffer = ObjectDifferBuilder.buildDefault();
		DiffNode diff = objectDiffer.compare(working, base);
		LogBean logBean = new LogBean();
		Log log = logBean.getLog();
		List<LogContent> logContents = logBean.getLogContents();
		ModelDesc modelDesc = (ModelDesc) clazz.getDeclaredAnnotation(ModelDesc.class);
		if (modelDesc == null) {
			return logBean;
		}
		log.setTableName(modelDesc.value());
		Table table = (Table) clazz.getDeclaredAnnotation(Table.class);
		if (table != null) {
			log.setRemark(table.name());
		}
		log.setCreatDate(new Date());
		log.setType(operateType.getValue());
		log.setAdminId(0L);
		log.setTableId(idVlue == null ? null :(Long)idVlue);
		System.out.println(JSONObject.toJSONString(log, true));
		Long logId =  differDao.insertAndGetGeneratedKeys(log);
		diff.visit(new DiffNode.Visitor() {
			public void node(DiffNode node, Visit visit) {
				final Object baseValue = node.canonicalGet(base);
				final Object workingValue = node.canonicalGet(working);
				if (!(node.getValueType() == clazz)) {
					try {
						Field field = clazz.getDeclaredField(node.getPropertyName());
						FieldDesc fieldDesc = field.getAnnotation(FieldDesc.class);
						if (fieldDesc != null) {
							final String message = node.getPropertyName() + " changed from " + baseValue + " to "
									+ workingValue;
							System.out.println("-------" + message);
							if (operateType == OperateType.UPDATE) {
								if (workingValue != null) {
									LogContent logContent = new LogContent();
									logContent.setLogId(logId);
									logContent.setTableColumn(fieldDesc.value());
									logContent.setOldValue(baseValue==null?null:baseValue.toString());
									logContent.setNewValue(workingValue.toString());
									logContents.add(logContent);
								}
							} else if (operateType == OperateType.DELEET) {
								LogContent logContent = new LogContent();
								logContent.setLogId(logId);
								logContent.setTableColumn(fieldDesc.value());
								logContent.setOldValue(baseValue.toString());
								logContent.setNewValue(null);
								logContent.setRemark("刪除");
								logContents.add(logContent);
							} else {
								LogContent logContent = new LogContent();
								logContent.setLogId(logId);
								logContent.setTableColumn(fieldDesc.value());
								logContent.setOldValue(null);
								logContent.setNewValue(workingValue.toString());
								logContents.add(logContent);
							}
							
						}
					} catch (Exception e) {
						e.printStackTrace();
					}

				}
			}
		});
		if(!CollectionUtils.isEmpty(logContents)) {
			differDao.insertList(logContents);
		}
		return logBean;
	}

}
